module rej_sample (
	input				clk,
	input 				rst_n,
	input 				enable,
	input 	[47:0]		data_in,
	output	reg	[95:0]	data_out,
	input				read_en,
	output	reg			valid_o,
	output				done
	
);

	parameter	MOL_Q = 12'd3329;

	reg	[47:0]	result_temp;
	reg [83:0]	data_out_temp2;
	reg	[3:0]	rej_cnt;
	reg	[2:0]	rej_cnt1;
	reg	[4:0]	rej_sam_cnt;
	reg 		read_en_buffer;
	reg			valid_o_buffer;


	always@(posedge clk or negedge rst_n)
	begin 
		if(!rst_n)
			read_en_buffer <= 1'b0;
		else if(read_en & enable)
			read_en_buffer <= 1'b1;
		else
			read_en_buffer <= 1'b0;
	end

	always@(posedge clk or negedge rst_n)
	begin 
		if(!rst_n)
			result_temp <= 48'b0;
		else if(read_en & enable)
			result_temp <= data_in[47:0];
		else
			result_temp <= 48'b0;
	end


	genvar i;

	generate
		for(i=0;i<4;i=i+1)begin:reject
			always@(posedge clk or negedge rst_n)
			begin
				if(!rst_n)
					rej_cnt[i] <= 1'b0;
				else if(read_en && enable)
					rej_cnt[i] <= data_in[12*i+11:12*i] < MOL_Q;
				else
					rej_cnt[i] <= 1'b0;
			end
		end
	endgenerate


	always@(posedge clk or negedge rst_n)
	begin 
		if(!rst_n)
			rej_sam_cnt <= 5'b0;
		else if(~enable)
			rej_sam_cnt <= 5'b0;
		else 
			if(valid_o)
				rej_sam_cnt <= rej_sam_cnt + 1'b1;
			else
				rej_sam_cnt <= rej_sam_cnt;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			rej_cnt1 <= 3'd0;
		else if(~enable | done)
			rej_cnt1 <= 3'd0;
		else if(read_en_buffer)
		begin
			if(rej_cnt1 > 3'd3)
				rej_cnt1 <= rej_cnt1 + rej_cnt[0] + rej_cnt[1] + rej_cnt[2] + rej_cnt[3] - 3'd4;
			else
				rej_cnt1 <= rej_cnt1 + rej_cnt[0] + rej_cnt[1] + rej_cnt[2] + rej_cnt[3];
		end
		else
			rej_cnt1 <= rej_cnt1;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			data_out_temp2 <= 84'b0;
		else if(~enable)
			data_out_temp2 <= 84'b0;
		else if(read_en_buffer)
		begin
			case(rej_cnt)
				4'b0000: data_out_temp2 <= data_out_temp2;
				4'b0001: data_out_temp2 <= {result_temp[11:0], data_out_temp2[83:12]};
				4'b0010: data_out_temp2 <= {result_temp[23:12],data_out_temp2[83:12]};
				4'b0100: data_out_temp2 <= {result_temp[35:24],data_out_temp2[83:12]};
				4'b1000: data_out_temp2 <= {result_temp[47:36],data_out_temp2[83:12]};
				4'b0011: data_out_temp2 <= {result_temp[23:12],result_temp[11:0], data_out_temp2[83:24]};
				4'b0101: data_out_temp2 <= {result_temp[35:24],result_temp[11:0], data_out_temp2[83:24]};
				4'b1001: data_out_temp2 <= {result_temp[47:36],result_temp[11:0], data_out_temp2[83:24]};
				4'b0110: data_out_temp2 <= {result_temp[35:24],result_temp[23:12],data_out_temp2[83:24]};	
				4'b1010: data_out_temp2 <= {result_temp[47:36],result_temp[23:12],data_out_temp2[83:24]};
				4'b1100: data_out_temp2 <= {result_temp[47:36],result_temp[35:24],data_out_temp2[83:24]};
				4'b0111: data_out_temp2 <= {result_temp[35:24],result_temp[23:12],result_temp[11:0], data_out_temp2[83:36]};
				4'b1011: data_out_temp2 <= {result_temp[47:36],result_temp[23:12],result_temp[11:0], data_out_temp2[83:36]};	
				4'b1101: data_out_temp2 <= {result_temp[47:36],result_temp[35:24],result_temp[11:0], data_out_temp2[83:36]};
				4'b1110: data_out_temp2 <= {result_temp[47:36],result_temp[35:24],result_temp[23:12],data_out_temp2[83:36]};
				4'b1111: data_out_temp2 <= {result_temp[47:36],result_temp[35:24],result_temp[23:12],result_temp[11:0],data_out_temp2[83:48]};
				default: data_out_temp2 <= data_out_temp2;
			endcase // rej_cnt
		end
		else
			data_out_temp2 <= data_out_temp2;
	end


	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			data_out <= 96'b0;
		else if(~enable)
			data_out <= 96'b0;
		else if(rej_cnt1 > 3'd3 && read_en_buffer)
		begin
			case(rej_cnt1)
				3'd4: data_out <= {data_out_temp2[83:36],data_out[95:48]};
				3'd5: data_out <= {data_out_temp2[71:24],data_out[95:48]};
				3'd6: data_out <= {data_out_temp2[59:12],data_out[95:48]};
				3'd7: data_out <= {data_out_temp2[47:0] ,data_out[95:48]};
				default: data_out <= data_out;
			endcase // rej_cnt1
		end
		else
			data_out <= data_out;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			valid_o_buffer <= 1'b0;
		else if(done || ~enable)
			valid_o_buffer <= 1'b0;
		else if(rej_cnt1 > 3'd3 && read_en_buffer)
			valid_o_buffer <= valid_o_buffer + 1'b1;
		else
			valid_o_buffer <= valid_o_buffer;
	end

	always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			valid_o <= 1'b0;
		else if(done || ~enable)
			valid_o <= 1'b0;
		else if(rej_cnt1 > 3'd3 && read_en_buffer && valid_o_buffer) 
			valid_o <= 1'b1;
		else
			valid_o <= 1'b0;
	end

	assign	done = (rej_sam_cnt == 5'd31 & valid_o);


endmodule